﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Threading;
using BinaryTimesCore;
using System.Windows.Interop;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;

namespace BinaryTimes
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Point? lastMousePosition;
        DispatcherTimer timerLabels;

        DeviceChangedAgent deviceChangedAgent;
        bool deviceRecognition;

        List<StatusMessage> statusMessages = new List<StatusMessage>();

        public MainWindow(bool deviceRecognition)
        {
            InitializeComponent();

            BinaryTimesInterfaceReceiver.StatusMessagesChanged += BinaryTimesInterfaceReceiver_StatusMessagesChanged;

            this.deviceRecognition = deviceRecognition;

            timerLabels = new DispatcherTimer();
            timerLabels.Interval = TimeSpan.FromMilliseconds(100);
            timerLabels.Tick += new EventHandler(timerLabels_Tick);

            if (deviceRecognition)
            {
                deviceChangedAgent = new DeviceChangedAgent(this);
                deviceChangedAgent.DeviceChanged += deviceChangedAgent_DeviceChanged;
            }
            else
            {
                this.MouseUp += MainWindow_MouseUp;
                this.KeyUp += MainWindow_KeyUp;
                this.MouseMove += MainWindow_MouseMove;
            }
        }


        void BinaryTimesInterfaceReceiver_StatusMessagesChanged()
        {
            statusMessages.Clear();
            statusMessages.AddRange(BinaryTimesInterfaceReceiver.StatusMessages.Skip(Math.Max(0, BinaryTimesInterfaceReceiver.StatusMessages.Count() - 4)).Take(4).Select(x => x.Value).ToList());

            if (statusMessages.Where(x => x.IsCritical).Any())
                this.Background = new ImageBrush(new BitmapImage(new Uri(@"pack://application:,,,/BinaryTimes;component/backgroundRed.png")));
            else
                this.Background = new ImageBrush(new BitmapImage(new Uri(@"pack://application:,,,/BinaryTimes;component/background.png")));

            if (statusMessages.Any())
            {
                timerLabels.Stop();
                timerLabels.Interval = TimeSpan.FromMilliseconds(100);
                timerLabels.Start();
            }
        }

        void deviceChangedAgent_DeviceChanged(object sender, DeviceChangedEventArgs e)
        {
            if (e.DeviceChangedAction == DeviceChangedAction.Arrival)
            {
                Close();
            }
        }

        void timerLabels_Tick(object sender, EventArgs e)
        {
            List<TextElement> tes = new List<TextElement>();

            int counter = 0;

            foreach (var item in statusMessages)
            {
                tes.Add(new TextElement
                {
                    BeginTime = TimeSpan.FromSeconds(counter * 3),
                    Duration = new Duration(TimeSpan.FromSeconds(3)),
                    FixedLocation = new Point(RandomNumbers.Next(100, this.ActualWidth - 100), RandomNumbers.Next(100, this.ActualHeight - 100)),
                    Mode = Helper.GetRandomTextElementMode(true),
                    Text = item.Text
                });

                counter++;
            }

            new TextElementAnimation(canvas, tes.ToArray()).Start();

            timerLabels.Interval = TimeSpan.FromSeconds(statusMessages.Count * 3);
        }

        private void storyboardInit_Completed(object sender, EventArgs e)
        {
            binaryClock1.Start();
        }

        void MainWindow_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            //Point position = e.GetPosition(this);

            //if (!lastMousePosition.HasValue)
            //{
            //    lastMousePosition = position;
            //}
            //else if (Math.Abs(lastMousePosition.Value.X - position.X) > 20 || Math.Abs(lastMousePosition.Value.Y - position.Y) > 20)
            //{
            //    Close();
            //}
        }

        void MainWindow_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            Close();
        }

        void MainWindow_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Close();
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(sender as Window).Handle);
            source.AddHook(new HwndSourceHook(WndProc));
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            //simulating CS_NOCLOSE
            if (msg == 0x112 && (LOWORD((int)wParam) & 0xfff0) == 0xf060)
                handled = true;

            return IntPtr.Zero;
        }

        private static int LOWORD(int n)
        {
            return (n & 0xffff);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            BinaryTimesInterfaceReceiver.Dispose();
        }
    }
}
